<?php

/*
    Assisted Array
    
        Author:     Alfredo Mungo
        License:    LGPL
        Copyright:  2012
*/

/*
  Class for assisted array management (non iterable).
  
  NOTE: When using this class for changing an array, the original data is not changed.
*/
class AArray implements ArrayAccess, IteratorAggregate, Serializable {

    private $data;
    
    function __construct($data)
    {
        if(!is_array($data))
            throw new WrongTypeException();
        
        $this->data = $data;
    }
    
    public function keys() { return array_keys($this->data); }
    public function values() { return $this->data; }
    
    public function length() { return count($this->data); }
    
    public function get($index)
    {
        if(!array_key_exists($index, $this->data))
            throw new IndexOutOfBoundException();
        return $this->data[$index];
    }
    
    public function set($index, $value)
    {
        $this->data[$index] = $value;
    }
    
    public function remove($key) { unset($this->data[$key]); }
    public function hasKey($key) { return array_key_exists($key, $this->data); }
    
    // Return a random value from the array
    public function random() { return $this->data[array_rand($this->data)]; }
    
    public function push($val) { $this->data[] = $val; }
    
    // Remove the last element of the array (if any), and return it
    public function pop() { return array_pop($this->data); }
    
    // Return a reversed version of the array
    public function reverse() { return new self(array_reverse($this->data)); }
    
    // Add en element at the beginning of the array
    public function prepend($val) { array_unshift($this->data, $val); }
    
    public function first() { $keys = array_keys($this->data); return $this->data[$keys[0]]; }
    public function last() { $k = array_keys($this->data); $c = count($k); return $this->data[$k[$c-1]]; }
    
    // Sorts the array and returns true on success, false on failure
    public function sort() { return sort($this->data); }
    
    // Reverse sort the array and returns true on success, false on failure
    public function sortReverse() { return rsort($this->data); }
    
    public function original() { return $this->data; }
    
    // ArrayAccess implementation
    public function offsetExists($offset) { return hasKey($offset); }
    public function offsetGet($offset) { return get($offset); }
    public function offsetSet($offset, $value) { set($offset, $value); }
    public function offsetUnset($offset) { remove($offset); }
    // ArrayAccess implementation END

    // IteratorAggregate implementation
    public function getIterator() {
        $it = new ArrayIterator($this->data);
        return $it;
    }
    // IteratorAggregate implementation END
    
    // Serializable implementation
    public function serialize() {
        $serialized = serialize($this->data);
        return $serialized;
    }
    
    public function unserialize($serialized) {
        $this->data = unserialize($serialized);
    }
    // Serializable implementation END
}

?>